#!/usr/bin/env python3
"""
OPC UA 模拟服务器
用于测试OPC UA设备连接
"""

import asyncio
import logging
import random
import time
from datetime import datetime

try:
    from asyncua import Server, ua
    OPCUA_AVAILABLE = True
except ImportError:
    OPCUA_AVAILABLE = False
    print("❌ opcua库未安装，请运行: pip install asyncua")

class MockOPCUAServer:
    """模拟OPC UA服务器"""
    
    def __init__(self, endpoint="opc.tcp://127.0.0.1:49320"):
        self.endpoint = endpoint
        self.server = None
        self.running = False
        
    async def init_server(self):
        """初始化OPC UA服务器"""
        if not OPCUA_AVAILABLE:
            raise ImportError("opcua库未安装")
            
        self.server = Server()
        await self.server.init()
        
        # 设置端点
        self.server.set_endpoint(self.endpoint)
        
        # 设置服务器名称
        self.server.set_server_name("Mock Industrial OPC UA Server")
        
        # 设置安全策略
        self.server.set_security_policy([
            ua.SecurityPolicyType.NoSecurity,
            ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt,
            ua.SecurityPolicyType.Basic256Sha256_Sign
        ])
        
        # 创建命名空间
        uri = "http://mock.industrial.opcua.server"
        idx = await self.server.register_namespace(uri)
        
        # 创建对象节点
        objects = self.server.get_objects_node()
        
        # 创建设备文件夹
        pump_folder = await objects.add_folder(idx, "1#混流泵")
        
        # 创建变频器频率变量 (VD300)
        self.vfd_frequency = await pump_folder.add_variable(
            idx, "VD300", 50.0, ua.VariantType.Float
        )
        await self.vfd_frequency.set_writable()
        
        # 添加更多测试变量
        self.motor_current = await pump_folder.add_variable(
            idx, "VD302", 15.5, ua.VariantType.Float
        )
        
        self.pump_pressure = await pump_folder.add_variable(
            idx, "VD304", 2.5, ua.VariantType.Float
        )
        
        # 运行状态
        self.pump_running = await pump_folder.add_variable(
            idx, "M100", True, ua.VariantType.Boolean
        )
        
        logging.info(f"✅ OPC UA服务器初始化完成")
        logging.info(f"📍 端点: {self.endpoint}")
        logging.info(f"🔧 命名空间: {uri} (索引: {idx})")
        
    async def start_server(self):
        """启动服务器"""
        try:
            await self.init_server()
            
            # 启动服务器
            await self.server.start()
            self.running = True
            
            logging.info("🚀 OPC UA模拟服务器已启动")
            logging.info("📊 可用节点:")
            logging.info("   - ns=2;i=300 (VD300) - 变频器频率")
            logging.info("   - ns=2;i=302 (VD302) - 电机电流") 
            logging.info("   - ns=2;i=304 (VD304) - 泵压力")
            logging.info("   - ns=2;i=100 (M100)  - 运行状态")
            
            # 启动数据更新任务
            asyncio.create_task(self.update_data())
            
        except Exception as e:
            logging.error(f"❌ 启动OPC UA服务器失败: {e}")
            raise
    
    async def stop_server(self):
        """停止服务器"""
        if self.server and self.running:
            await self.server.stop()
            self.running = False
            logging.info("🛑 OPC UA模拟服务器已停止")
    
    async def update_data(self):
        """更新模拟数据"""
        while self.running:
            try:
                # 模拟变频器频率波动 (45-55 Hz)
                frequency = 50.0 + random.uniform(-5, 5)
                await self.vfd_frequency.set_value(frequency)
                
                # 模拟电机电流变化 (10-20 A)
                current = 15.0 + random.uniform(-5, 5)
                await self.motor_current.set_value(current)
                
                # 模拟泵压力变化 (2.0-3.0 bar)
                pressure = 2.5 + random.uniform(-0.5, 0.5)
                await self.pump_pressure.set_value(pressure)
                
                # 模拟运行状态切换 (95%概率运行)
                running = random.random() > 0.05
                await self.pump_running.set_value(running)
                
                # 每秒更新一次
                await asyncio.sleep(1)
                
            except Exception as e:
                logging.error(f"❌ 更新数据失败: {e}")
                await asyncio.sleep(5)

async def main():
    """主函数"""
    logging.basicConfig(
        level=logging.INFO,
        format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
    )
    
    if not OPCUA_AVAILABLE:
        print("💡 安装opcua库:")
        print("   pip install asyncua")
        return
    
    server = MockOPCUAServer()
    
    try:
        await server.start_server()
        
        print("\n🎯 OPC UA模拟服务器运行中...")
        print("📍 端点: opc.tcp://127.0.0.1:49320")
        print("🔧 测试节点: ns=2;i=300 (VD300)")
        print("⏹️  按 Ctrl+C 停止服务器\n")
        
        # 保持运行
        while True:
            await asyncio.sleep(1)
            
    except KeyboardInterrupt:
        print("\n👋 收到停止信号，正在关闭服务器...")
    except Exception as e:
        logging.error(f"💥 服务器异常: {e}")
    finally:
        await server.stop_server()

if __name__ == "__main__":
    asyncio.run(main()) 